﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 2010-7-5
 * Time: 22:47
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.IO;
using System.Reflection;

using ECCIT;

namespace ECCIT.Utilities
{
	/// <summary>
    /// Description of ReflectorUtil.
	/// </summary>
	public sealed class ReflectorUtil
	{
        public readonly static AppDomain CurrentDomain = AppDomain.CurrentDomain;

        public static PropertyInfo GetProperty(string typeName, string propertyName)
        {
            Type type = Type.GetType(typeName);
            if (type == null)
                throw new Exception("Type: " + typeName + " not found.");

            PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);

            return property;
        }

        public static ResultInfo InvokeMethod(string assemblyPath, string typeName, string methodName, object[] args)
        {
            ResultInfo result = ResultInfo.False;
            string message = string.Empty;

            Assembly assembly = Assembly.LoadFile(assemblyPath);
            
            Type type = assembly.GetType(typeName);
            if (type == null)
            {
                result.Message = "Type: " + typeName + " not found.";
                return result;
            }

            ConstructorInfo constructor = type.GetConstructor(new Type[] { });
            if (constructor == null)
            {
                result.Message = "Constructor of Type: " + typeName + " not found.";
                return result;
            }

            BindingFlags methodFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod;
            MethodInfo method = type.GetMethod(methodName, methodFlags);
            if (method == null)
            {
                result.Message = "Method : " + methodName + " of Type: " + typeName + " not found.";
                return result;
            }

            ParameterInfo[] parms = method.GetParameters();
            if (parms.Length != args.Length)
            {
                result.Message = "The parameter size of invoked method: " + methodName + " is " + parms.Length + ". But the actual passed parameter size is: " + args.Length;
                return result;
            }

            for (int i = 0; i < parms.Length; i++)
            {
                if (!parms[i].ParameterType.Equals(args[i].GetType()))
                {
                    result.Message = "The type of No. " + (i+1) + " parameter is " + parms[i].ParameterType.FullName + ", but not " + args[i].GetType().FullName;
                    return result;
                }
            }

            try
            {
                object obj = constructor.Invoke(BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, null, null);
                object returnedObj = type.InvokeMember(methodName, methodFlags, null, obj, args);
                result = ResultInfo.True;
                result.ReturnObject = returnedObj;
                return result;
            }
            catch (Exception ex)
            {
                result.Message = string.Format("Error occurred in {0}.InvokeMethod. Message: {1}", "ReflectorUtil", ex.Message);
                result.Exception = ex;
                return result;
            }
        }
    }
}
